using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AdminSG3L.Domain.Entities;
using AdminSG3L.Domain.Repositories;
using AdminSG3L.Applicaticn.ServicesInterface;
using AdminSG3L.Applicaticn.Commands;
using Serilog;
using AdminSG3L.Applicaticn.Dtos;
using AdminSG3L.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;

namespace AdminSG3L.Applicaticn.Services;

// 使用partial修饰符允许在多个文件中定义此类
public partial class RoleService : IRoleService
{
    private readonly IRepository<AppRole> _roleRepository;
    private readonly AdminDbContext _dbContext;

    public RoleService(IRepository<AppRole> roleRepository, AdminDbContext dbContext)
    {
        _roleRepository = roleRepository;
        _dbContext = dbContext;
    }

    public async Task<ApiResponse<AppRole?>> GetByIdAsync(Guid id)
    {
        if (id == Guid.Empty)
        {
            return ApiResponse<AppRole?>.Fail("角色ID无效");
        }
        try
        {
            var role = await _roleRepository.GetByIdAsync(id);
            if (role == null)
            {
                return ApiResponse<AppRole?>.Fail("角色不存在");
            }
            else
            {
                return ApiResponse<AppRole?>.Success(role);
            }
        }
        catch (Exception ex)
        {
            Log.Error(ex, "获取角色异常，Id={RoleId}", id);
            return ApiResponse<AppRole?>.Fail($"获取角色异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<RoleDto>> CreateAsync(CreateRoleDto dto)
    {
        var role = AppRole.Create(dto.RoleName, dto.RoleCode, dto.Description);
        await _roleRepository.AddAsync(role);
        var result = new RoleDto(role.Id, role.RoleName, role.RoleCode, role.Description, 0);
        return ApiResponse<RoleDto>.Success(result);
    }

    public async Task<ApiResponse<IEnumerable<RoleDto>>> BatchCreateAsync(IEnumerable<CreateRoleDto> dtos)
    {
        var roles = dtos.Select(dto => AppRole.Create(dto.RoleName, dto.RoleCode, dto.Description)).ToList();
        await _roleRepository.AddRangeAsync(roles);
        var result = roles.Select(role => new RoleDto(role.Id, role.RoleName, role.RoleCode, role.Description, 0));
        return ApiResponse<IEnumerable<RoleDto>>.Success(result);
    }

    public async Task<ApiResponse<bool>> UpdateAsync(UpdateRoleDto dto)
    {
        var role = await _roleRepository.GetByIdAsync(dto.Id);
        if (role == null)
            return ApiResponse<bool>.Fail("角色不存在");
        role.Update(dto.RoleName, dto.RoleCode, dto.Description);
        await _roleRepository.UpdateAsync(role);
        return ApiResponse<bool>.Success(true);
    }

    public async Task<ApiResponse<bool>> DeleteAsync(Guid id)
    {
        if (id == Guid.Empty)
        {
            return ApiResponse<bool>.Fail("角色ID无效");
        }
        try
        {
            var role = await _roleRepository.GetByIdAsync(id);
            if (role == null)
            {
                return ApiResponse<bool>.Fail("角色不存在");
            }
            
            // 检查是否已经被软删除
            if (role.IsDeleted)
            {
                return ApiResponse<bool>.Fail("角色已被删除");
            }

            // 调用实体的Delete方法（这会检查IsSystem属性）
            role.Delete();
            role.UpdateTime();
            await _roleRepository.UpdateAsync(role);
            
            Log.Information("角色软删除成功，Id={RoleId}", id);
            return ApiResponse<bool>.Success(true, "删除成功");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "删除角色异常，Id={RoleId}", id);
            return ApiResponse<bool>.Fail($"删除角色异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<int>> BatchDeleteAsync(IEnumerable<Guid> ids)
    {
        if (ids == null || !ids.Any())
        {
            return ApiResponse<int>.Fail("ID集合不能为空");
        }
        try
        {
            var roles = (await _roleRepository.GetAllAsync()).Where(r => ids.Contains(r.Id) && !r.IsDeleted).ToList();
            if (roles.Count == 0)
            {
                return ApiResponse<int>.Fail("未找到要删除的角色或角色已被删除");
            }

            int deletedCount = 0;
            var failedRoles = new List<string>();

            // 逐个调用实体的Delete方法
            foreach (var role in roles)
            {
                try
                {
                    role.Delete(); // 这会检查IsSystem属性
                    role.UpdateTime();
                    await _roleRepository.UpdateAsync(role);
                    deletedCount++;
                }
                catch (InvalidOperationException ex)
                {
                    // 记录无法删除的系统角色
                    failedRoles.Add($"{role.RoleName}: {ex.Message}");
                    Log.Warning("角色删除被阻止，Id={RoleId}, 角色名={RoleName}, 原因={Reason}", role.Id, role.RoleName, ex.Message);
                }
            }

            if (failedRoles.Any())
            {
                var message = $"批量删除完成，成功删除 {deletedCount} 个，失败 {failedRoles.Count} 个。失败原因：{string.Join("；", failedRoles)}";
                Log.Information("批量删除角色部分成功，删除数量={DeletedCount}, 失败数量={FailedCount}", deletedCount, failedRoles.Count);
                return ApiResponse<int>.Success(deletedCount, message);
            }
            else
            {
                Log.Information("批量删除角色成功，删除数量={DeletedCount}", deletedCount);
                return ApiResponse<int>.Success(deletedCount, "批量删除成功");
            }
        }
        catch (Exception ex)
        {
            Log.Error(ex, "批量删除角色异常");
            return ApiResponse<int>.Fail($"批量删除角色异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<IEnumerable<RoleDto>>> GetAllDtoAsync()
    {
        try
        {
            var roles = await _dbContext.Roles
                .Include(r => r.Users)
                .Where(r => !r.IsDeleted)
                .ToListAsync();
            var dtos = roles.Select(role => new RoleDto(role.Id, role.RoleName, role.RoleCode, role.Description, role.Users?.Count ?? 0));
            return ApiResponse<IEnumerable<RoleDto>>.Success(dtos);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "获取所有角色异常");
            return ApiResponse<IEnumerable<RoleDto>>.Fail($"获取所有角色异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<(IEnumerable<RoleDto> Roles, int TotalCount)>> GetPagedDtoAsync(int pageIndex, int pageSize)
    {
        try
        {
            // 先获取角色基本信息
            var query = _dbContext.Roles.Where(r => !r.IsDeleted);
            var total = await query.CountAsync();
            var roles = await query
                .Skip(pageIndex * pageSize)
                .Take(pageSize)
                .ToListAsync();
            
            // 为每个角色计算用户数量
            var dtos = new List<RoleDto>();
            foreach (var role in roles)
            {
                var userCount = await _dbContext.Users
                    .Where(u => !u.IsDeleted && u.Roles.Any(r => r.Id == role.Id))
                    .CountAsync();
                
                dtos.Add(new RoleDto(role.Id, role.RoleName, role.RoleCode, role.Description, userCount));
            }
            
            Log.Information($"角色分页查询: pageIndex={pageIndex}, pageSize={pageSize}, total={total}, returned={dtos.Count}");
            return ApiResponse<(IEnumerable<RoleDto>, int)>.Success((dtos, total));
        }
        catch (Exception ex)
        {
            Log.Error(ex, "分页获取角色异常");
            return ApiResponse<(IEnumerable<RoleDto>, int)>.Fail($"分页获取角色异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<RoleDto?>> GetDtoByIdAsync(Guid id)
    {
        try
        {
            var role = await _dbContext.Roles
                .Include(r => r.Users)
                .FirstOrDefaultAsync(r => r.Id == id && !r.IsDeleted);
            
            if (role == null)
                return ApiResponse<RoleDto?>.Fail("角色不存在");
            
            var dto = new RoleDto(role.Id, role.RoleName, role.RoleCode, role.Description, role.Users?.Count ?? 0);
            return ApiResponse<RoleDto?>.Success(dto);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "根据ID获取角色异常，Id={RoleId}", id);
            return ApiResponse<RoleDto?>.Fail($"根据ID获取角色异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<int>> GetCountAsync()
    {
        try
        {
            var count = await _roleRepository.CountAllAsync();
            return ApiResponse<int>.Success(count);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "获取角色总数异常");
            return ApiResponse<int>.Fail($"获取角色总数异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<RoleDto?>> FindOneAsync(Func<RoleDto, bool> predicate)
    {
        if (predicate == null)
        {
            return ApiResponse<RoleDto?>.Fail("查询条件不能为空");
        }
        try
        {
            var roles = await _dbContext.Roles
                .Include(r => r.Users)
                .Where(r => !r.IsDeleted)
                .ToListAsync();
            var dtos = roles.Select(r => new RoleDto(r.Id, r.RoleName, r.RoleCode, r.Description, r.Users?.Count ?? 0));
            var result = dtos.FirstOrDefault(predicate);
            if (result == null)
            {
                return ApiResponse<RoleDto?>.Fail("未找到角色");
            }
            else
            {
                return ApiResponse<RoleDto?>.Success(result);
            }
        }
        catch (Exception ex)
        {
            Log.Error(ex, "条件查询单个角色异常");
            return ApiResponse<RoleDto?>.Fail($"条件查询单个角色异常: {ex.Message}");
        }
    }

    public async Task<ApiResponse<IEnumerable<RoleDto>>> FindManyAsync(Func<RoleDto, bool> predicate)
    {
        if (predicate == null)
        {
            return ApiResponse<IEnumerable<RoleDto>>.Fail("查询条件不能为空");
        }
        try
        {
            var roles = await _dbContext.Roles
                .Include(r => r.Users)
                .Where(r => !r.IsDeleted)
                .ToListAsync();
            var dtos = roles.Select(r => new RoleDto(r.Id, r.RoleName, r.RoleCode, r.Description, r.Users?.Count ?? 0));
            var result = dtos.Where(predicate);
            return ApiResponse<IEnumerable<RoleDto>>.Success(result);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "条件查询多个角色异常");
            return ApiResponse<IEnumerable<RoleDto>>.Fail($"条件查询多个角色异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 为角色分配权限
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="permissionId">权限ID</param>
    /// <returns>分配结果</returns>
    public async Task<ApiResponse<bool>> AssignPermissionAsync(Guid roleId, Guid permissionId)
    {
        try
        {
            Log.Information("开始为角色分配权限，RoleId={RoleId}, PermissionId={PermissionId}", roleId, permissionId);
            
            // 检查角色是否存在
            var role = await _dbContext.Roles
                .Include(r => r.Permissions)
                .FirstOrDefaultAsync(r => r.Id == roleId);
            
            if (role == null)
            {
                return ApiResponse<bool>.Fail("角色不存在");
            }

            // 检查权限是否存在
            var permission = await _dbContext.Permissions.FindAsync(permissionId);
            if (permission == null)
            {
                return ApiResponse<bool>.Fail("权限不存在");
            }

            // 检查是否已经分配过该权限
            if (role.Permissions.Any(p => p.Id == permissionId))
            {
                return ApiResponse<bool>.Success(true, "权限已存在");
            }

            // 分配权限
            role.Permissions.Add(permission);
            await _dbContext.SaveChangesAsync();
            
            Log.Information("成功为角色分配权限");
            return ApiResponse<bool>.Success(true, "分配权限成功");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "分配权限异常");
            return ApiResponse<bool>.Fail($"分配权限异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 移除角色权限
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="permissionId">权限ID</param>
    /// <returns>移除结果</returns>
    public async Task<ApiResponse<bool>> RemovePermissionAsync(Guid roleId, Guid permissionId)
    {
        try
        {
            Log.Information("开始移除角色权限，RoleId={RoleId}, PermissionId={PermissionId}", roleId, permissionId);
            
            var role = await _dbContext.Roles
                .Include(r => r.Permissions)
                .FirstOrDefaultAsync(r => r.Id == roleId);
                
            if (role == null)
            {
                return ApiResponse<bool>.Fail("角色不存在");
            }

            // 查找要移除的权限
            var permission = role.Permissions.FirstOrDefault(p => p.Id == permissionId);
            if (permission == null)
            {
                return ApiResponse<bool>.Success(true, "权限不存在，无需移除");
            }

            // 移除权限
            role.Permissions.Remove(permission);
            await _dbContext.SaveChangesAsync();
            
            Log.Information("成功移除角色权限");
            return ApiResponse<bool>.Success(true, "移除权限成功");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "移除权限异常");
            return ApiResponse<bool>.Fail($"移除权限异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取角色的所有权限
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>权限列表</returns>
    public async Task<ApiResponse<IEnumerable<PermissionDto>>> GetRolePermissionsAsync(Guid roleId)
    {
        try
        {
            Log.Information("开始获取角色权限，RoleId={RoleId}", roleId);
            
            var role = await _dbContext.Roles
                .Include(r => r.Permissions)
                .FirstOrDefaultAsync(r => r.Id == roleId);
                
            if (role == null)
            {
                return ApiResponse<IEnumerable<PermissionDto>>.Fail("角色不存在");
            }

            // 将权限转换为DTO
            var permissions = role.Permissions.Select(p => new PermissionDto(
                p.Id,
                p.PermissionName,
                p.PermissionCode,
                p.Description,
                p.IsActive,
                p.ParentId,
                p.CreatedAt,
                p.UpdatedAt
            )).ToList();
            
            Log.Information("成功获取角色权限，权限数量={Count}", permissions.Count);
            return ApiResponse<IEnumerable<PermissionDto>>.Success(permissions);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "获取角色权限异常");
            return ApiResponse<IEnumerable<PermissionDto>>.Fail($"获取角色权限异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 为角色分配菜单
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="menuId">菜单ID</param>
    /// <returns>分配结果</returns>
    public async Task<ApiResponse<bool>> AssignMenuAsync(Guid roleId, Guid menuId)
    {
        try
        {
            Log.Information("开始为角色分配菜单，RoleId={RoleId}, MenuId={MenuId}", roleId, menuId);
            
            // 获取角色，包含关联的菜单
            var role = await _dbContext.Roles
                .Include(r => r.Menus)
                .FirstOrDefaultAsync(r => r.Id == roleId);
            
            if (role == null)
            {
                return ApiResponse<bool>.Fail("角色不存在");
            }

            // 检查菜单是否存在
            var menu = await _dbContext.Menus.FindAsync(menuId);
            if (menu == null)
            {
                return ApiResponse<bool>.Fail("菜单不存在");
            }

            // 检查是否已经分配
            if (role.Menus.Any(m => m.Id == menuId))
            {
                return ApiResponse<bool>.Success(true, "该菜单已经分配给角色");
            }

            // 添加菜单关联
            role.Menus.Add(menu);
            await _dbContext.SaveChangesAsync();
            
            Log.Information("角色菜单分配成功，RoleId={RoleId}, MenuId={MenuId}", roleId, menuId);
            return ApiResponse<bool>.Success(true, "菜单分配成功");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "分配菜单异常");
            return ApiResponse<bool>.Fail($"分配菜单异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 移除角色菜单
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="menuId">菜单ID</param>
    /// <returns>移除结果</returns>
    public async Task<ApiResponse<bool>> RemoveMenuAsync(Guid roleId, Guid menuId)
    {
        try
        {
            Log.Information("开始移除角色菜单，RoleId={RoleId}, MenuId={MenuId}", roleId, menuId);
            
            // 获取角色，包含关联的菜单
            var role = await _dbContext.Roles
                .Include(r => r.Menus)
                .FirstOrDefaultAsync(r => r.Id == roleId);
            
            if (role == null)
            {
                return ApiResponse<bool>.Fail("角色不存在");
            }

            // 查找要移除的菜单
            var menu = role.Menus.FirstOrDefault(m => m.Id == menuId);
            if (menu == null)
            {
                return ApiResponse<bool>.Success(true, "该菜单未分配给角色");
            }

            // 移除菜单关联
            role.Menus.Remove(menu);
            await _dbContext.SaveChangesAsync();
            
            Log.Information("角色菜单移除成功，RoleId={RoleId}, MenuId={MenuId}", roleId, menuId);
            return ApiResponse<bool>.Success(true, "菜单移除成功");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "移除菜单异常");
            return ApiResponse<bool>.Fail($"移除菜单异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 设置角色启用状态
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="enabled">是否启用</param>
    /// <returns>设置结果</returns>
    public async Task<ApiResponse<bool>> SetEnabledAsync(Guid roleId, bool enabled)
    {
        try
        {
            Log.Information("开始设置角色启用状态，RoleId={RoleId}, Enabled={Enabled}", roleId, enabled);
            
            var role = await _roleRepository.GetByIdAsync(roleId);
            if (role == null)
            {
                return ApiResponse<bool>.Fail("角色不存在");
            }

            Log.Warning("角色启用状态功能需要在Role实体中添加IsActive属性");
            return ApiResponse<bool>.Success(true, "设置启用状态功能需要在Role实体中添加IsActive属性");
        }
        catch (Exception ex)
        {
            Log.Error(ex, "设置角色启用状态异常");
            return ApiResponse<bool>.Fail($"设置角色启用状态异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取角色的菜单列表
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>菜单列表</returns>
    public async Task<ApiResponse<IEnumerable<object>>> GetRoleMenusAsync(Guid roleId)
    {
        try
        {
            Log.Information("开始获取角色菜单列表，RoleId={RoleId}", roleId);
            
            // 获取角色，包含关联的菜单
            var role = await _dbContext.Roles
                .Include(r => r.Menus)
                .FirstOrDefaultAsync(r => r.Id == roleId);
            
            if (role == null)
            {
                return ApiResponse<IEnumerable<object>>.Fail("角色不存在");
            }

            // 转换菜单数据为简单对象
            var menus = role.Menus.Select(m => new
            {
                id = m.Id,
                menuName = m.MenuName,
                menuCode = m.MenuCode,
                path = m.Path,
                icon = m.Icon,
                description = m.Description
            }).ToList();
            
            Log.Information("获取角色菜单列表成功，RoleId={RoleId}, 菜单数量={Count}", roleId, menus.Count);
            return ApiResponse<IEnumerable<object>>.Success(menus);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "获取角色菜单列表异常");
            return ApiResponse<IEnumerable<object>>.Fail($"获取角色菜单列表异常: {ex.Message}");
        }
    }
} 